package utils

import (
	"fmt"
	"github.com/pkg/errors"
	"gitlab.local/DO-module/new-filemanage-module/src/constant"
	"gitlab.local/DO-module/new-filemanage-module/src/core/sqlitedb/sqlitemodel"
	"gitlab.local/DO-module/new-filemanage-module/src/service/access"
	"gitlab.local/golibrary/utils"
	"gorm.io/gorm"
	"os"
	"path/filepath"
	"strings"
)

func GetAllUserAppAccess(database *gorm.DB, username string) (result map[string]bool) {
	result = make(map[string]bool)

	ADMIN := access.GetAdmin()

	usersMapGroup := make([]sqlitemodel.GroupUsers, 0)
	_ = database.Table("group_users").Where("username=?", username).Find(&usersMapGroup).Error
	gs, isadmin := UserGroup(usersMapGroup, username)
	appdata := make([]sqlitemodel.AppAccessUser, 0)
	_ = database.Model(sqlitemodel.AppAccessUser{}).Where(fmt.Sprintf("username in (%s)", gs)).Find(&appdata).Error
	appmap := AppAccessMap(appdata)
	allapplist := access.GetAllAppAccessList()
	if len(allapplist) > 0 {
		for _, item := range allapplist {
			ac := false
			if ADMIN == username {
				ac = true
				result[item.AppId] = ac
				continue
			}
			appmap1, ok := appmap[item.AppId]
			if ok {
				if access.CheckAppAccessByAccessMap(appmap1) {
					ac = true
				}
			} else {
				if isadmin {
					ac = true
				} else {
					if item.IsDefault {
						ac = true
					}
				}
			}
			result[item.AppId] = ac
		}
	}
	return
}

// GetOneAccessInfo 根据用户名、appid 判断权限
func GetOneAccessInfo(database *gorm.DB, user string, appid string) (code bool) {
	code = true
	ADMIN := access.GetAdmin()
	if ADMIN == user {
		return true
	}
	appdata := make([]sqlitemodel.AppAccessUser, 0)
	_ = database.Model(sqlitemodel.AppAccessUser{}).Where("username=? and app_id=?", user, appid).Find(&appdata).Error

	usersMapGroup := make([]sqlitemodel.GroupUsers, 0)
	_ = database.Table("group_users").Where("username=?", user).Find(&usersMapGroup).Error
	if len(appdata) > 0 {
		if appdata[0].IsAllow != 1 {
			code = false
		}
		return
	}
	gs, isadmin := UserGroup(usersMapGroup, user)
	appdata = make([]sqlitemodel.AppAccessUser, 0)
	_ = database.Model(sqlitemodel.AppAccessUser{}).Where(fmt.Sprintf("username in (%s)", gs)).Find(&appdata).Error
	appmap := AppAccessMap(appdata)
	appmap1, ok := appmap[appid]
	code = false

	if (ok && access.CheckAppAccessByAccessMap(appmap1)) || (!ok && (isadmin || (!isadmin && access.CheckAppDefault(appid)))) {
		code = true
	}

	return
}

func UserGroup(groups []sqlitemodel.GroupUsers, username string) (result string, admin bool) {
	result = fmt.Sprintf("'%s'", username)
	if len(groups) > 0 {
		for _, item := range groups {
			if item.GroupName == "@admin" {
				admin = true
			}
			result = fmt.Sprintf("%s,'%s'", result, item.GroupName)
		}
	}
	return
}

func AppAccessMap(applist []sqlitemodel.AppAccessUser) (result map[string]access.AccessMap) {
	result = make(map[string]access.AccessMap)
	if len(applist) > 0 {
		for _, item := range applist {
			res := make(access.AccessMap)
			res[item.Username] = item.IsAllow
			_, ok := result[item.AppId]
			if ok {
				result[item.AppId][item.Username] = item.IsAllow
			} else {
				result[item.AppId] = res
			}
		}
	}
	return
}

func getUserConfigDir(name string) (string, error) {
	if name == "" {
		return "", errors.New("invalid user")
	}
	if !utils.Exists(constant.CustomConf) {
		err := utils.MkdirPerm(constant.CustomConf, 0755)
		if err != nil {
			return "", errors.Wrapf(err, "mkdir %s failed", constant.CustomConf)
		}
	}
	configFileDIr := filepath.Join(constant.CustomConf, name)
	if !utils.Exists(configFileDIr) {
		if err := os.MkdirAll(configFileDIr, 0755); err != nil {
			return "", errors.Wrapf(err, "mkdir %s failed", configFileDIr)
		}
		_ = os.Chmod(configFileDIr, 0755)
	}
	return configFileDIr, nil
}

func GetUserConfigPath(userName, fileName string) (string, error) {
	configDir, _ := getUserConfigDir(userName)
	userFilePath := fmt.Sprintf("%s/%s", configDir, fileName)
	if !utils.Exists(userFilePath) {
		//_, err := os.OpenFile(fileName, os.O_CREATE, 0755)
		// 应该为userFilePath，否则会在根目录下直接创建该文件，在解决该问题时就发现根目录下存在三个json文件。
		_, err := os.OpenFile(userFilePath, os.O_CREATE, 0755)
		if err != nil {
			return userFilePath, errors.Wrapf(err, "mkdir %s failed", userFilePath)
		}
	}
	return userFilePath, nil
}

// GetBUserConfig
// @Description: 获取配置文件,返回二进制
// @param userName
// @return userData
// @return err
func GetBUserConfig(userName, fileName string) ([]byte, error) {
	configFile, err := GetUserConfigPath(userName, fileName)
	if err != nil {
		return nil, errors.New("failed to get configPath error")
	}

	bytes, readErr := os.ReadFile(configFile)
	if readErr != nil {
		return nil, errors.New("failed to read config error")
	}
	//if jsonErr := json.Unmarshal(bytes, &configData); jsonErr != nil {
	//	return UserConfig{}, errors.New("failed to json parse error")
	//}
	return bytes, nil
}

func ReWriteLanguage(lang, s string) string {
	if s != "" && strings.Contains(s, "%s") {
		s = fmt.Sprintf(s, lang)
	}
	return s
}
